/*
 * Copyright (c) 2018 - 2028. www.vtuzx.com Inc. All Rights Reserved
 */
package com.vtuzx.kingdee.xqc_api.service.impl;

import com.vtuzx.core.VtuzxException;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.bean.dto.VtuzxPage;
import com.vtuzx.core.bean.dto.VtuzxToken;
import com.vtuzx.core.constant.IVtuzxConst;
import com.vtuzx.core.file.excel.VtuzxExcel;
import com.vtuzx.core.file.excel.VtuzxExcelCell;
import com.vtuzx.core.file.excel.VtuzxExcelRow;
import com.vtuzx.core.file.excel.VtuzxExcelSheet;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.fast.dao.setting.CharacterDao;
import com.vtuzx.fast.dao.setting.DictDao;
import com.vtuzx.fast.utils.FastUtil;
import com.vtuzx.kingdee.xqc_api.service.IXqcAllocationService;
import com.vtuzx.kingdee.xqc_api.service.IXqcInventoryService;
import com.vtuzx.kingdee.xqc_api.service.IXqcSyncKingdeeOrderService;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterial;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterialBox;
import com.vtuzx.kingdee.xqc_core.constant.BillEvent;
import com.vtuzx.kingdee.xqc_core.constant.BillStatus;
import com.vtuzx.kingdee.xqc_core.constant.BillType;
import com.vtuzx.kingdee.xqc_core.constant.IXqcConst;
import com.vtuzx.kingdee.xqc_core.dao.*;
import com.vtuzx.kingdee.xqc_core.service.IJiKeYunApiService;
import com.vtuzx.web.bean.VtuzxDownloadBean;
import com.vtuzx.web.dao.mongo.CustomerDao;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import javax.print.Doc;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class XqcAllocationServiceImpl implements IXqcAllocationService {

    /**
     * Logger
     */
    private static final Logger _logger = LoggerFactory.getLogger(XqcAllocationServiceImpl.class);


    @Autowired
    StockDetailDao stockDetailDao;

    @Autowired
    InventoryDao inventoryDao;

    @Autowired
    InventoryDetailDao inventoryDetailDao;

    @Autowired
    MaterialDao materialDao;

    @Autowired
    AllocationDao allocationDao;

    @Autowired
    AllocationDetailDao allocationDetailDao;

    @Autowired
    AllocationDetailBoxDao allocationDetailBoxDao;

    @Autowired
    private IXqcInventoryService inventoryService;

    @Autowired
    private IXqcSyncKingdeeOrderService syncKingdeeOrderService;

    @Autowired
    private SaleStoreDetailDao saleStoreDetailDao;

    @Autowired
    private DictDao dictDao;

    @Autowired
    private StockDao stockDao;

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private CharacterDao characterDao;

    @Autowired
    private StoreTokenDao storeTokenDao;

    @Autowired
    private IJiKeYunApiService iJiKeYunApiService;

    public static VtuzxMap list2Map(List<? extends Map<String, Object>> dataList, String keyCol) {
        VtuzxMap ret = new VtuzxMap();
        for(Map<String, Object> m: dataList) {
            String key = VtuzxUtil.getString(m, keyCol);
            if (!VtuzxUtil.isEmpty(key)) {
                ret.put(key, m);
            }
        }
        return ret;
    }

    public VtuzxMap getOptions(Map<String, Object> param) {
        List<String> keys = VtuzxUtil.getObject(param, "keys");
        Iterator<Document> dictList = dictDao.findList(Criteria.where("key").in(keys).and("effect").is(true), null, 0, 0);
        VtuzxMap retMap = new VtuzxMap();
        while (dictList.hasNext()) {
            Document dict = dictList.next();
            List<VtuzxMap> options = new ArrayList<>();
            String key = VtuzxUtil.getObject(dict, "key");
            retMap.put(key, options);
            List<Document> dbs = VtuzxUtil.getObject(dict, "details");
            if (dbs != null) {
                sortDictDetails(dbs);
                for (Document detail : dbs) {
                    if (VtuzxUtil.getBoolean(detail, "effect")) {
                        VtuzxMap dictDetail = new VtuzxMap("key", VtuzxUtil.getString(detail, "key"))
                                .append("name", VtuzxUtil.getString(detail, "name"))
                                .append("remark", VtuzxUtil.getString(detail, "remark"));
                        options.add(dictDetail);
                    }
                }
            }
        }
        return retMap;
    }

    private void sortDictDetails(List<Document> details) {
        details.sort((o1, o2) -> {
            int sort1 = VtuzxUtil.getInt(o1, "sort");
            String key1 = VtuzxUtil.getString(o1, "key");
            int sort2 = VtuzxUtil.getInt(o2, "sort");
            String key2 = VtuzxUtil.getString(o2, "key");
            return sort1 == sort2 ? key1.compareTo(key2) : sort1 - sort2;
        });
    }


    @Override
    public VtuzxMap getLocationNoList(ObjectId userId, String name, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        List<VtuzxMap> locationNoList = new ArrayList<>();
        Iterator<Document> stockDocItr = stockDetailDao.findList(Criteria.where("fNumber").is(stockNo), null, 0, 0);
        while (stockDocItr.hasNext()) {
            VtuzxMap stockMap = new VtuzxMap();
            Document stockDoc = stockDocItr.next();
            stockMap.append("locationNo", VtuzxUtil.getString(stockDoc, "locationNo"));
            stockMap.append("locationName", VtuzxUtil.getString(stockDoc, "locationName"));
            locationNoList.add(stockMap);
        }
        return new VtuzxMap("data", locationNoList);
    }

    @Override
    public VtuzxMap getUserAllocationRfid(List<String> rfidList) {
        Iterator<Document> boxItr = inventoryDetailDao.findList(Criteria.where("rfid").in(rfidList).and("status").is("in"), null, 0, 0);
        List<VtuzxMap> dataList = new ArrayList<>();
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            VtuzxMap data = getAllocationBoxInner(boxDoc);
            dataList.add(data);
        }
        int boxNoSize = rfidList.size();
        int dataSize = dataList.size();
        return new VtuzxMap("data", dataList).append("message", String.format("总计输入了rfid为%s，有效箱数为%s", boxNoSize, dataSize));
    }

    @Override
    public VtuzxMap getUserAllocationBoxList(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String boxNoKey = VtuzxUtil.getObject(param, "boxNo");
        String stockNo = VtuzxUtil.getObject(param, "stockNo");
        String locationNo = VtuzxUtil.getObject(param, "locationNo");
        Criteria cond = new Criteria();
        cond.and("status").is("in").and("stockNo").is(stockNo).and("locationNo").is(locationNo);
        // 管理箱号
        String boxNo;
        // 实际箱号
        boolean isBC = false;
        if (boxNoKey.contains("|;")) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 5) {
                boxNo = boxNoKey;
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo + "|;batch";
                isBC = true;
            } else {
                boxNo = boxValues[boxValues.length - 1];
            }
            cond.and("boxNo").is(boxNo);
        } else {
            boxNo = boxNoKey;
            if (boxNo.startsWith("T")) {
                cond.and("trayNumber").is(boxNo);
            } else if (boxNo.startsWith("http")) {
                String boxNoStr = boxNo.substring(boxNo.indexOf("Z"));
                //查询数组中的值等于xxx
                Document conDoc = new Document("$elemMatch", new Document("status", "in").append("traceBackNo", boxNoStr));
                Document conTwoDoc = new Document("$elemMatch", new Document("status", "in").append("traceBackNo", boxNo));
                cond.orOperator(Criteria.where("traceBack").is(new Document("traceBack", conDoc)), Criteria.where("traceBack").is(conTwoDoc));
            } else {
                cond.and("boxNo").is(boxNo);
            }
        }

        List<VtuzxMap> dataList  = new ArrayList<>();
        VtuzxMap data;
        Iterator<Document> boxItr = inventoryDetailDao.findList(cond, null, 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            data = getAllocationBoxInner(boxDoc);
            if (boxNo.startsWith("http")) {
                data.append("traceBack", boxNo);
                data.append("isZS", true);
            }

            if (isBC) {
                data.append("barcodeType", "BC");
            } else {
                data.append("barcodeType", "");
            }
            dataList.add(data);
        }

        if (dataList.size() == 0) {
            throw new VtuzxException("箱号不在库");
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    private VtuzxMap getAllocationBoxInner(Document boxDoc) {
        VtuzxMap data = new VtuzxMap(boxDoc);
        data.append("id", VtuzxUtil.removeString(data, "_id"));
        data.remove(IVtuzxConst.Key_createTime);
        data.remove(IVtuzxConst.Key_updateTime);
        data.remove("_createUserId");
        data.remove("_updateUserId");
        data.append("_inventoryId", VtuzxUtil.removeString(data, "_inventoryId"));

        String _inventoryId = VtuzxUtil.getString(data, "_inventoryId");
        Document inventoryDoc = inventoryDao.findOne(Criteria.where(IVtuzxConst.Key__id).is(new ObjectId(_inventoryId)));
        String materialNo = VtuzxUtil.getString(inventoryDoc, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        String materialName = VtuzxUtil.getString(materialDoc, "fName");
        String materialSpec = VtuzxUtil.getString(materialDoc, "fSpecification");
        String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        String unitName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
        String batchNo = VtuzxUtil.getString(inventoryDoc, "batchNo");
        int exp = VtuzxUtil.getInt(inventoryDoc, "exp");
        String produceDate = VtuzxUtil.getString(inventoryDoc, "produceDate");
        data.append("materialName", materialName)
                .append("materialNo", materialNo)
                .append("materialSpec", materialSpec)
                .append("unit", unit)
                .append("unitName", unitName)
                .append("exp", exp)
                .append("produceDate", produceDate)
                .append("batchNo", batchNo);
        return data;
    }

    @Override
    public void addUserAllocationBox(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        boolean isSale = VtuzxUtil.getBoolean(param, "isSale");
        addUserAllocationBoxInner(userId, name, param, isSale, "");
    }

    @Override
    public void addUserPurInMaterialBoxList(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        boolean isSale = VtuzxUtil.getBoolean(param, "isSale");
        String saleBillNo = VtuzxUtil.getString(param, "saleBillNo");
        for (Map<String, Object> box: boxList) {
            addUserAllocationBoxInner(userId, name, box, isSale, saleBillNo);
        }
    }

    private void addUserAllocationBoxInner(ObjectId userId, String name, Map<String, Object> data, boolean isSale, String saleBillNo) throws VtuzxException {

        VtuzxMap optionParam = new VtuzxMap();
        List<String> optionKeys = new ArrayList<>();
        optionKeys.add("allocationStock");
        optionParam.append("keys", optionKeys);

        VtuzxMap optionsMap = getOptions(optionParam);
        List<VtuzxMap> allocationOptions = VtuzxUtil.getObject(optionsMap, "allocationStock");
        VtuzxMap allocationOptionMap = list2Map(allocationOptions, "name");
        VtuzxMap toStockNoMap = VtuzxUtil.getObject(allocationOptionMap, "toStockNo");
        String toStockNoKey = VtuzxUtil.getString(toStockNoMap, "key");
        VtuzxMap toLocationNoMap = VtuzxUtil.getObject(allocationOptionMap, "toLocationNo");
        String toLocationNoKey = VtuzxUtil.getString(toLocationNoMap, "key");

        String stockNo = VtuzxUtil.getString(data, "stockNo");
        String locationNo = VtuzxUtil.getString(data, "locationNo");
        String traceBack = VtuzxUtil.getString(data, "traceBack");
        boolean isZS = VtuzxUtil.getBoolean(data, "isZS");
        String boxNo = "";
        boolean newBoxNo = false;
        String boxNoKey = VtuzxUtil.getString(data, "boxNo");
        String trayNumber = VtuzxUtil.getString(data, "trayNumber");
        String materialNo = VtuzxUtil.getString(data, "materialNo");
        String materialName = VtuzxUtil.getString(data, "materialName");
        String materialSpec = VtuzxUtil.getString(data, "materialSpec");
        String batchNo = VtuzxUtil.getString(data, "batchNo");
        String unit = VtuzxUtil.getString(data, "unit");
        double count = VtuzxUtil.getDouble(data, "count");
        double inputCount = VtuzxUtil.getDouble(data, "inputCount");
        int exp = VtuzxUtil.getInt(data, "exp");
        String produceDate = VtuzxUtil.getString(data, "produceDate");
        String rfid = VtuzxUtil.getString(data, "rfid");
        String allocationType = VtuzxUtil.getString(data, "allocationType");
        String toStockNo = VtuzxUtil.getString(data, "toStockNo");
        String toLocationNo = VtuzxUtil.getString(data, "toLocationNo");
        double surplusCount = count - inputCount;

        if (inputCount > 0 && surplusCount > 0) {
            boxNo = boxNoKey.substring(0, 3) + new Date().getTime();
            newBoxNo = true;
        } else {
            boxNo = boxNoKey;
        }
        Criteria pickCond = new Criteria("boxNo").is(boxNo).and("isTemp").is(true);
        if (isZS) {
            pickCond.and("traceBack").is(traceBack);
        }
        Document boxMap = allocationDetailBoxDao.findOne(pickCond);
        if (!VtuzxUtil.isEmpty(boxMap)) {
            String createUserName = VtuzxUtil.getString(boxMap, "createUserName");
            throw new VtuzxException("箱号已存在，请勿重复添加！【扫码人员：" + createUserName + "】");
        }

        Criteria detailCond = Criteria.where("stockNo").is(stockNo);
        detailCond.and("isTemp").is(true);
        detailCond.and("materialNo").is(materialNo);
        detailCond.and("batchNo").is(batchNo);
        detailCond.and("allocationType").is(allocationType);
        Document detail = allocationDetailDao.findOne(detailCond);
        Document updateVal = new Document();

        if (detail == null) {
            updateVal.append("isTemp", true);
            updateVal.append("stockNo", stockNo);
            updateVal.append("locationNo", locationNo);
            updateVal.append("materialNo", materialNo);
            updateVal.append("materialName", materialName);
            updateVal.append("materialSpec", materialSpec);
            updateVal.append("batchNo", batchNo);
            updateVal.append("unit", unit);
            updateVal.append("_createUserId", userId);
            updateVal.append("createUserName", name);
            updateVal.append("boxCount", 1);
            updateVal.append("produceDate", produceDate);
            updateVal.append("exp", exp);
            updateVal.append("allocationType", allocationType);
            if (isSale) {
                updateVal.append("isSale", true);
                updateVal.append("toStockNo", toStockNoKey);
                updateVal.append("toLocationNo", toLocationNoKey);
                updateVal.append("saleBillNo", saleBillNo);
            } else {
                updateVal.append("toStockNo", toStockNo);
                updateVal.append("toLocationNo", toLocationNo);
            }
            if (inputCount > 0 && surplusCount > 0) {
                updateVal.append("count", inputCount);
            } else {
                if (isZS) {
                updateVal.append("count", 1);
            } else {
                updateVal.append("count", count);
            }
            }
        } else {
            if (inputCount > 0 && surplusCount > 0) {
                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", inputCount));
            } else {
                if (isZS) {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", 1));
                } else {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
                }
            }
        }
        ObjectId _detailId;
        if (detail == null) {
            _detailId = allocationDetailDao.insertOne(updateVal);
        } else {
            _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
            allocationDetailDao.updateByIdRedirect(_detailId, updateVal);
        }

        Document detailBox = new Document();
        detailBox.append("isTemp", true);
        detailBox.append("_detailId", _detailId);
        detailBox.append("materialNo", materialNo);
        detailBox.append("materialName", materialName);
        detailBox.append("materialSpec", materialSpec);
        detailBox.append("boxNo", boxNo);
        detailBox.append("batchNo", batchNo);
        detailBox.append("_createUserId", userId);
        detailBox.append("createUserName", name);
        detailBox.append("stockNo", stockNo);
        detailBox.append("locationNo", locationNo);
        detailBox.append("unit", unit);
        detailBox.append("rfid", rfid);
        detailBox.append("allocationType", allocationType);
        detailBox.append("trayNumber", trayNumber);
        if (isSale) {
            detailBox.append("isSale", true);
            detailBox.append("toStockNo", toStockNoKey);
            detailBox.append("toLocationNo", toLocationNoKey);
        }
        if (inputCount > 0 && surplusCount > 0) {
            detailBox.append("count", inputCount);
            detailBox.append("beforeCount", count);
            detailBox.append("beforeBoxNo", boxNoKey);
            detailBox.append("newBoxNo", newBoxNo);
        } else {
            if (isZS) {
                detailBox.append("traceBack", traceBack);
                detailBox.append("isZS", true);
                detailBox.append("count", 1);
            } else {
                detailBox.append("count", count);
            }
        }
        allocationDetailBoxDao.insertOne(detailBox);
    }


    @Override
    public VtuzxMap saveUserAllocation(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {

        VtuzxMap optionParam = new VtuzxMap();
        List<String> optionKeys = new ArrayList<>();
        optionKeys.add("allocationStock");
        optionParam.append("keys", optionKeys);

        VtuzxMap optionsMap = getOptions(optionParam);
        List<VtuzxMap> allocationOptions = VtuzxUtil.getObject(optionsMap, "allocationStock");
        VtuzxMap allocationOptionMap = list2Map(allocationOptions, "name");
        VtuzxMap toStockNoMap = VtuzxUtil.getObject(allocationOptionMap, "toStockNo");
        String toStockNoKey = VtuzxUtil.getString(toStockNoMap, "key");
        VtuzxMap toLocationNoMap = VtuzxUtil.getObject(allocationOptionMap, "toLocationNo");
        String toLocationNoKey = VtuzxUtil.getString(toLocationNoMap, "key");

        String billNo = VtuzxUtil.getString(param, "billNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String locationNo = VtuzxUtil.getString(param, "locationNo");
        String toStockNo = VtuzxUtil.getString(param, "toStockNo");
        String toLocationNo = VtuzxUtil.getString(param, "toLocationNo");
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        String remark = VtuzxUtil.getString(param, "remark");
        boolean isSale = VtuzxUtil.getBoolean(param, "isSale");
        String saleBillNo = VtuzxUtil.getString(param, "saleBillNo");

        Criteria cond = new Criteria("_createUserId").is(userId).and("isTemp").is(true);
        if (isSale) {
            cond.and("isSale").is(true);
        }
        int sumBoxCount = 0;
        double sumCount = 0d;
        List<Document> allocationList = new ArrayList<>();
        Iterator<Document> detailItr = allocationDetailDao.findList(cond, null, 0, 0);
        while (detailItr.hasNext()) {
            Document detailDoc = detailItr.next();
            int boxCount = VtuzxUtil.getInt(detailDoc, "boxCount");
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            sumBoxCount += boxCount;
            sumCount += count;
            allocationList.add(detailDoc);
        }
        Document allocationDoc = new Document();
        allocationDoc.append("stockNo", stockNo)
                .append("locationNo", locationNo)
                .append("allocationType", allocationType)
                .append("boxCount", sumBoxCount)
                .append("count", sumCount)
                .append("remark", remark)
                .append("status", BillStatus.Save.toString());
        if (isSale) {
            allocationDoc.append("isSale", true);
            allocationDoc.append("saleBillNo", saleBillNo);
            allocationDoc.append("toStockNo", toStockNoKey);
            allocationDoc.append("toLocationNo", toLocationNoKey);
        } else {
            allocationDoc.append("toStockNo", toStockNo);
            allocationDoc.append("toLocationNo", toLocationNo);
        }


        if (VtuzxUtil.isEmpty(billNo)) {
            billNo = IXqcConst.createBillNo(BillType.DBYK);
            allocationDoc.append("billNo", billNo);
            Document updateDoc = new Document();
            if (isSale) {
                updateDoc.append("$set", new Document("billNo", billNo).append("toStockNo", toStockNoKey).append("toLocationNo", toLocationNoKey).append("allocationType", allocationType))
                        .append("$unset", new Document("isTemp", 1).append("isSale", 1));

                //反写销售单数量
                for (Document allocation: allocationList) {
                    String materialNo = VtuzxUtil.getString(allocation, "materialNo");
                    double count = VtuzxUtil.getDouble(allocation, "count");
                    Document saleUpdateDoc = new Document();
                    saleUpdateDoc.append("$inc", new VtuzxMap("pickCount", count).append("surplusCount", -count));
                    saleStoreDetailDao.updateOneRedirect(Criteria.where("materialNo").is(materialNo).and("billNo").is(saleBillNo), saleUpdateDoc);
                }
            } else {
                updateDoc.append("$set", new Document("billNo", billNo).append("toStockNo", toStockNo).append("toLocationNo", toLocationNo).append("allocationType", allocationType))
                        .append("$unset", new Document("isTemp", 1));
            }
            allocationDao.insertBill(userId, name, allocationDoc);
            allocationDetailDao.updateManyRedirect(cond, updateDoc);
            allocationDetailBoxDao.updateManyRedirect(cond, updateDoc);
        } else {
            allocationDoc.remove("allocationType");
            allocationDoc.remove("billNo");
            allocationDoc.remove("boxCount");
            allocationDoc.remove("status");
            allocationDoc.append("billNo", billNo);

            allocationDao.updateOne(Criteria.where("billNo").is(billNo), allocationDoc);
        }
        Criteria criteria = new Criteria("billNo").is(billNo);
        //判断是整托调拨还是部分调拨
        Iterator<Document> detailBoxItr = allocationDetailBoxDao.findList(criteria,null,0,0);
        List<String> trayList = new ArrayList<>();//托盘编号
        while (detailBoxItr.hasNext()){
            Document detailBoxDoc = detailBoxItr.next();
            String trayNum = VtuzxUtil.getString(detailBoxDoc,"trayNumber");
            if(!trayList.contains(trayNum)){
                trayList.add(trayNum);
            }
        }
        for (String trayNum : trayList){

            criteria.and("trayNumber").is(trayNum)
                    .and("stockNo").is(stockNo);
            long count = allocationDetailBoxDao.count(criteria);
            long inventoryCount = inventoryDetailDao.count(new Criteria("trayNumber").is(trayNum)
                    .and("status").is("in").and("stockNo").is(stockNo));
            if (count != inventoryCount){
                Document updateDoc = new Document();
                updateDoc.append("$unset", new Document("trayNumber", ""));

            allocationDetailBoxDao.updateManyRedirect(criteria, updateDoc);
            }
        }

        if (isSale) {
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("billNo", billNo);
            data.put("beforeStockNo", stockNo);
            data.put("toStockNo", toStockNo);
            auditUserAllocation(userId, name, data);
        }
        return new VtuzxMap("billNo", billNo);
    }

    @Override
    public void auditUserAllocation(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String beforeStockNo = VtuzxUtil.getString(param, "beforeStockNo");
        String toStockNo = VtuzxUtil.getString(param,"toStockNo");
//        String trayNumber = VtuzxUtil.getString(param, "trayNumber");
        List<BillMaterial> allocationDetailList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        List<VtuzxMap> bcBoxList = new ArrayList<>();
        List<Document> zsBoxList = new ArrayList<>();
        Criteria criteria = new Criteria("billNo").is(billNo);
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(criteria, null, 0, 0);
        Iterator<Document> allocationDetailBoxItr = allocationDetailBoxDao.findList(criteria, null, 0, 0);
        List<Document> allocationDetailBoxList = new ArrayList<>();
        while (allocationDetailBoxItr.hasNext()) {
            Document allocationDetailBoxDoc = allocationDetailBoxItr.next();
            allocationDetailBoxList.add(allocationDetailBoxDoc);
        }

        List<Document> allocationList = new ArrayList<>();//吉客云
        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            allocationList.add(allocationDetailDoc);
            BillMaterial billMaterial = new BillMaterial();
            ObjectId _allocationDetailId = allocationDetailDoc.getObjectId(IVtuzxConst.Key__id);
            billMaterial.setMaterialNo(VtuzxUtil.getString(allocationDetailDoc, "materialNo"));
            billMaterial.setUnit(VtuzxUtil.getString(allocationDetailDoc, "unit"));
            billMaterial.setBatchNo(VtuzxUtil.getString(allocationDetailDoc, "batchNo"));
            billMaterial.setProduceDate(VtuzxUtil.getString(allocationDetailDoc, "produceDate"));
            billMaterial.setExp(VtuzxUtil.getInt(allocationDetailDoc, "exp"));
            billMaterial.setStockNo(VtuzxUtil.getString(allocationDetailDoc, "toStockNo"));
            billMaterial.setLocationNo(VtuzxUtil.getString(allocationDetailDoc, "toLocationNo"));
            List<BillMaterialBox> boxList = new ArrayList<>();
            for (Document allocationDetailBox: allocationDetailBoxList) {
                ObjectId detailId = VtuzxUtil.getObject(allocationDetailBox, "_detailId");
                if (detailId.equals(_allocationDetailId)) {
                    BillMaterialBox box = new BillMaterialBox();
                    String boxNo = VtuzxUtil.getString(allocationDetailBox, "boxNo");
                    String innTrayNumber = VtuzxUtil.getString(allocationDetailBox, "trayNumber");
                    String locationNo = VtuzxUtil.getString(allocationDetailBox, "locationNo");
                    box.setRfid(VtuzxUtil.getString(allocationDetailBox, "rfid"));
                    double count = VtuzxUtil.getDouble(allocationDetailBox, "count");
                    boolean isZS = VtuzxUtil.getBoolean(allocationDetailBox, "isZS");
                    String traceBack = VtuzxUtil.getString(allocationDetailBox, "traceBack");
                    boolean newBoxNo = VtuzxUtil.getBoolean(allocationDetailBox, "newBoxNo");
                    box.setBoxNo(boxNo);
                    box.setTraceBackNo(traceBack);
                    box.setTrayNumber(innTrayNumber);
                    box.setCount(count);
                    box.setLocationNo(VtuzxUtil.getString(allocationDetailDoc, "toLocationNo"));
                    if (isZS) {
                        box.setIsZS(true);
                    }
                    boxList.add(box);
                    String[] boxValues = boxNo.split("\\|\\;");
                    if (boxValues.length == 3) {
                        // 已入库包材长度为3
                        bcBoxList.add(new VtuzxMap("boxNo", boxNo)
                                .append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue())
                                .append("locationNo", locationNo));
                    } else {
                        if (newBoxNo) {
                            String beforeBoxNo = VtuzxUtil.getString(allocationDetailBox, "beforeBoxNo");
                            bcBoxList.add(new VtuzxMap("boxNo", beforeBoxNo)
                                .append("count", BigDecimal.valueOf(count).setScale(0, RoundingMode.HALF_UP).intValue())
                                .append("locationNo", locationNo));
                        } else {
                            if (isZS) {
                                zsBoxList.add(new Document("traceBack", traceBack).append("boxNo", boxNo));
                            } else {
                                boxNoList.add(boxNo);
                            }
                        }
                    }
                }
                billMaterial.setBoxList(boxList);
            }
            allocationDetailList.add(billMaterial);

        }
        allocationDao.audit(userId, name, billNo);
        Document allocationDoc = allocationDao.findOne(Criteria.where("billNo").is(billNo));
        String allocationType = VtuzxUtil.getString(allocationDoc, "allocationType");
        try {
            inventoryService.reduceInventory(userId, name, BillEvent.Audit, BillType.DBCK, beforeStockNo, billNo, boxNoList, bcBoxList, zsBoxList);
            inventoryService.addInventoryTran(userId, name, BillEvent.Audit, BillType.DBRK, billNo, allocationDetailList);
            try {
                syncKingdeeOrderService.syncStockTransferOrderMain(userId, name, billNo, allocationType);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
        } catch(Exception e) {
            allocationDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", BillStatus.Save.toString()));
            throw e;
        }
        //如果调拨是这三个仓库并且调拨人是原料库管传极客云入库
        if (toStockNo.equals("020") || toStockNo.equals("021") || toStockNo.equals("022")){
            Document customerDoc = customerDao.findOne(Criteria.where("_id").is(userId));
            List<ObjectId> characterIds = VtuzxUtil.getObject(customerDoc,"_characterIds");
            Iterator<Document> characterItr = characterDao.findList(Criteria.where("_id").in(characterIds),null,0,0);
            List<String> nameList = new ArrayList<>();
            while (characterItr.hasNext()){
                Document characterDoc = characterItr.next();
                String characterName = VtuzxUtil.getString(characterDoc,"name");
                nameList.add(characterName);
            }
            if (nameList.contains("原料库管") || nameList.contains("超级管理员")){
                //获取令牌
                Document storeDoc = storeTokenDao.findOne(Criteria.where("type").is("kingdee"));
                List<VtuzxMap> stockInDetailViews = new ArrayList<>();//入库申请单明细
                String intWarehouseCode = "XQWG00101";//仓库编码
                for (Document data:allocationList){
                    String materialNo = VtuzxUtil.getString(data,"materialNo");
                    double sumCount = VtuzxUtil.getDouble(data,"count");
                    String dbBillNo =VtuzxUtil.getString(data,"billNo");
                    //需要先获取条码(skubarcode)
                    VtuzxMap goodsMap = new VtuzxMap();//getGoodsList方法返回值
                    VtuzxMap goodsParam = new VtuzxMap();
                    goodsParam.append("pageIndex", 0)
                            .append("pageSize", 1)
                            .append("goodsNo", materialNo);
                    try {
                        goodsMap = iJiKeYunApiService.getGoodsList(storeDoc, goodsParam);
                    } catch (Exception e) {
                        throw new VtuzxException(e.getMessage());
                    }
                    LinkedHashMap result = VtuzxUtil.getObject(goodsMap, "result");
                    LinkedHashMap dataMap = VtuzxUtil.getObject((Map<String, Object>) result, "data");
                    List<LinkedHashMap> goods = VtuzxUtil.getObject((Map<String, Object>) dataMap, "goods");
                    if (goods != null && goods.size() > 0){
                        LinkedHashMap goodsResult = goods.get(0);
                        String skuBarcode = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuBarcode");
                        VtuzxMap map = new VtuzxMap();
                        map.append("relDetailId",dbBillNo)
                                .append("skuCount",sumCount).append("isCertified",1)
                                .append("skuBarcode",skuBarcode);
                        stockInDetailViews.add(map);
                    }
                }
                //创建极客云入库单
                VtuzxMap stockParam = new VtuzxMap();//入库参数
                stockParam.append("intWarehouseCode", intWarehouseCode)//仓库
                        .append("inType", 102)
                        .append("relDataId", billNo)//关联单据编号
                        .append("applyDate", VtuzxUtil.formatYmdHmsF(new Date()))
                        .append("operator", name)
                        .append("source", "OPEN")
                        .append("notificationCode","100")
                        .append("stockInDetailViews", stockInDetailViews);

                //创建入库单
                try {
                    iJiKeYunApiService.createStockIn(storeDoc, stockParam);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
            }
        }
    }

    @Override
    public void unauditUserAllocation(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        List<BillMaterial> allocationDetailList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        List<VtuzxMap> bcBoxList = new ArrayList<>();
        Criteria criteria = new Criteria("billNo").is(billNo);
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(criteria, null, 0, 0);
        Iterator<Document> allocationDetailBoxItr = allocationDetailBoxDao.findList(criteria, null, 0, 0);
        List<Document> allocationDetailBoxList = new ArrayList<>();
        while (allocationDetailBoxItr.hasNext()) {
            Document allocationDetailBoxDoc = allocationDetailBoxItr.next();
            allocationDetailBoxList.add(allocationDetailBoxDoc);
        }

        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            BillMaterial billMaterial = new BillMaterial();
            ObjectId _allocationDetailId = allocationDetailDoc.getObjectId(IVtuzxConst.Key__id);
            billMaterial.setMaterialNo(VtuzxUtil.getString(allocationDetailDoc, "materialNo"));
            billMaterial.setUnit(VtuzxUtil.getString(allocationDetailDoc, "unit"));
            billMaterial.setBatchNo(VtuzxUtil.getString(allocationDetailDoc, "batchNo"));
            billMaterial.setProduceDate(VtuzxUtil.getString(allocationDetailDoc, "produceDate"));
            billMaterial.setExp(VtuzxUtil.getInt(allocationDetailDoc, "exp"));
            billMaterial.setStockNo(VtuzxUtil.getString(allocationDetailDoc, "stockNo"));
            List<BillMaterialBox> boxList = new ArrayList<>();
            for (Document allocationDetailBox: allocationDetailBoxList) {
                ObjectId detailId = VtuzxUtil.getObject(allocationDetailBox, "_detailId");
                if (detailId.equals(_allocationDetailId)) {
                    BillMaterialBox box = new BillMaterialBox();
                    String boxNo = VtuzxUtil.getString(allocationDetailBox, "boxNo");
                    box.setBoxNo(boxNo);
                    box.setRfid(VtuzxUtil.getString(allocationDetailBox, "rfid"));
                    double count = VtuzxUtil.getDouble(allocationDetailBox, "count");
                    box.setCount(count);
                    box.setLocationNo(VtuzxUtil.getString(allocationDetailDoc, "locationNo"));
                    boxList.add(box);
                    String[] boxValues = boxNo.split("\\|\\;");
                    if (boxValues.length == 3) {
                        // 已入库包材长度为3
                        bcBoxList.add(new VtuzxMap("boxNo", boxNo).append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue()));
                    } else {
                        boxNoList.add(boxNo);
                    }
                }
                billMaterial.setBoxList(boxList);
            }
            allocationDetailList.add(billMaterial);

        }
        Criteria cond = new Criteria("billNo").is(billNo);
        Document doc = new Document("isTemp", true);
        allocationDao.unaudit(billNo);
        if ("pda".equals(allocationType)) {
            allocationDetailDao.updateMany(cond, doc);
            allocationDetailBoxDao.updateMany(cond, doc);
        }
        try {
            inventoryService.reduceInventory(userId, name, BillEvent.Audit, BillType.DBCK, billNo, boxNoList, bcBoxList);

            inventoryService.addInventory(userId, name, BillEvent.Audit, BillType.DBRK, billNo, allocationDetailList);

        } catch(Exception e) {
            allocationDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", BillStatus.Save.toString()));
            throw e;
        }
    }

    @Override
    public void deleteAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document allocationDoc = allocationDao.findOne(Criteria.where("billNo").is(billNo));
        String allocationType = VtuzxUtil.getString(allocationDoc, "allocationType");
        String saleBillNo = VtuzxUtil.getString(allocationDoc, "saleBillNo");
        List<Document> allocationList = new ArrayList<>();
        if ("sale".equals(allocationType)) {
            Iterator<Document> detailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detailDoc = detailItr.next();
                allocationList.add(detailDoc);
            }
            for (Document allocation: allocationList) {
                String materialNo = VtuzxUtil.getString(allocation, "materialNo");
                int count = VtuzxUtil.getInt(allocation, "count");
                Document saleUpdateDoc = new Document();
                saleUpdateDoc.append("inc", new VtuzxMap("pickCount", -count).append("surplusCount", count));
                saleStoreDetailDao.updateOneRedirect(Criteria.where("materialNo").is(materialNo).and("billNo").is(saleBillNo), saleUpdateDoc);
            }
        }
        allocationDao.deleteOne(Criteria.where("billNo").is(billNo));
        allocationDetailDao.deleteMany(Criteria.where("billNo").is(billNo));
        allocationDetailBoxDao.deleteMany(Criteria.where("billNo").is(billNo));
    }


    @Override
    public void deleteMaterialAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        Document material = allocationDetailDao.findById(id);
        String billNo = VtuzxUtil.getString(material, "billNo");
        allocationDetailDao.deleteById(id);

        double count = 0d;
        int boxCount = 0;
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (allocationDetailItr.hasNext()) {
            Document detail = allocationDetailItr.next();
            int detailBoxCount = VtuzxUtil.getInt(detail, "boxCount");
            double detailCount = VtuzxUtil.getDouble(detail, "count");
            count += detailCount;
            boxCount += detailBoxCount;
        }

        allocationDao.updateOne(Criteria.where("billNo").is(billNo), new Document("boxCount", boxCount).append("count", count));

        allocationDetailBoxDao.deleteMany(Criteria.where("_detailId").is(new ObjectId(id)));

    }

    @Override
    public void deleteBoxAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        Document box = allocationDetailBoxDao.findById(id);
        String billNo = VtuzxUtil.getString(box, "billNo");
        ObjectId _detailId = VtuzxUtil.getObject(box, "_detailId");
        allocationDetailBoxDao.deleteById(id);
        double count = 0d;
        int boxCount = 0;
        Iterator<Document> boxItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            count += VtuzxUtil.getDouble(boxDoc, "count");
            boxCount ++;
        }
        if (boxCount == 0) {
            allocationDetailDao.deleteById(_detailId);
        } else {
            allocationDetailDao.updateById(_detailId, new Document("count", count).append("boxCount", boxCount));
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            double scanCount = 0d;
            int scanBoxCount = 0;
            Iterator<Document> scanBoxItr = allocationDetailBoxDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (scanBoxItr.hasNext()) {
                Document boxDoc = boxItr.next();
                scanCount += VtuzxUtil.getDouble(boxDoc, "count");
                scanBoxCount ++;
            }
            allocationDao.updateOne(Criteria.where("billNo").is(billNo), new Document("boxCount", scanBoxCount).append("count", scanCount));
        }
    }

    @Override
    public VtuzxMap getUserTask(ObjectId userId, String name, Map<String, Object> param) {
        List<VtuzxMap> dataList = new ArrayList<>();
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        Criteria cond = new Criteria("status").is("issue").and("stockNo").is(stockNo).and("allocationType").is("task").and("_allocationUserId").is(userId);
        Iterator<Document> allocationItr = allocationDao.findList(cond, null, 0, 0);
        while (allocationItr.hasNext()) {
            Document allocationDoc = allocationItr.next();
            VtuzxMap allocationMap = new VtuzxMap(allocationDoc);
            allocationMap.append("id", VtuzxUtil.removeString(allocationMap, IVtuzxConst.Key__id));
            allocationMap.append("createUserId", VtuzxUtil.removeString(allocationMap, "_createUserId"));
            dataList.add(allocationMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }


    @Override
    public VtuzxMap getUserMaterial(ObjectId userId, String name, Map<String, Object> param) {
        List<VtuzxMap> dataList = new ArrayList<>();
        String stock = VtuzxUtil.getString(param, "stockNo");
        Criteria cond = new Criteria("isTemp").is(true).and("_createUserId").is(userId);
        if (!VtuzxUtil.isEmpty(stock)) {
            cond.and("stockNo").is(stock);
        }
        Iterator<Document> allocationItr = allocationDetailDao.findList(cond, null, 0, 0);
        while (allocationItr.hasNext()) {
            Document allocationDoc = allocationItr.next();
            VtuzxMap allocationMap = new VtuzxMap(allocationDoc);
            allocationMap.append("id", VtuzxUtil.removeString(allocationMap, IVtuzxConst.Key__id));
            allocationMap.append("createUserId", VtuzxUtil.removeString(allocationMap, "_createUserId"));
            dataList.add(allocationMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getUserMaterialBox(ObjectId userId, String name, Map<String, Object> param) {
        List<VtuzxMap> dataList = new ArrayList<>();
        String detailId = VtuzxUtil.getString(param, "detailId");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(detailId)) {
            cond.and("_detailId").is(FastUtil.convertId(detailId));
        }
        Iterator<Document> allocationBoxItr = allocationDetailBoxDao.findList(cond, null, 0, 0);
        if (!VtuzxUtil.isEmpty(allocationBoxItr)) {
            while (allocationBoxItr.hasNext()) {
                Document allocationBox = allocationBoxItr.next();
                VtuzxMap allocationMap = new VtuzxMap(allocationBox);
                allocationMap.append("id", VtuzxUtil.removeString(allocationMap, IVtuzxConst.Key__id));
                allocationMap.append("createUserId", VtuzxUtil.removeString(allocationMap, "_createUserId"));
                allocationMap.append("detailId", VtuzxUtil.removeString(allocationMap, "_detailId"));
                dataList.add(allocationMap);
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getAllocationList(ObjectId userId, String name, Map<String, Object> param) {
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String toStockNo = VtuzxUtil.getString(param, "toStockNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        String auditUserName = VtuzxUtil.getString(param, "auditUserName");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        List<String> auditTime = VtuzxUtil.getObject(param, "auditTime");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        cond.and("count").gt(0);
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(allocationType)) {
            cond.and("allocationType").is(allocationType);
        }
        if (!VtuzxUtil.isEmpty(toStockNo)) {
            cond.and("toStockNo").is(toStockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            cond.and("createUserName").regex(createUserName);
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(auditUserName)) {
            cond.and("auditUserName").regex(auditUserName);
        }
        if (!VtuzxUtil.isEmpty(auditTime)) {
            cond.and("auditTime").gte(VtuzxUtil.parseDate(auditTime.get(0))).lte(VtuzxUtil.parseDate(auditTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> allocationNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> allocationDetailItr = allocationDetailDao.findList(pickCond, new Document("createTime",-1), 0, 0);
            while (allocationDetailItr.hasNext()) {
                Document allocationDetailDoc = allocationDetailItr.next();
                String allocationNo = VtuzxUtil.getString(allocationDetailDoc, "billNo");
                if (!allocationNoList.contains(allocationNo)) {
                    allocationNoList.add(allocationNo);
                }
            }

            List<VtuzxMap> allocationList = new ArrayList<>();
            long materialBomPickCount = allocationDao.count(cond.and("billNo").in(allocationNoList));
            Iterator<Document> allocationItr = allocationDao.findList(cond, new Document("createTime",-1), pageIndex, pageSize);
            while (allocationItr.hasNext()) {
                Document allocationDoc = allocationItr.next();
                VtuzxMap allocationMap = new VtuzxMap(allocationDoc);
                allocationMap.append("id", VtuzxUtil.getString(allocationMap, IVtuzxConst.Key__id));
                allocationMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(allocationMap, "createTime")));
                allocationList.add(allocationMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, allocationList);
        }

        VtuzxPage page = allocationDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("allocationType", VtuzxUtil.getString(doc, "allocationType"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("toStockNo", VtuzxUtil.getString(doc, "toStockNo"))
                .append("toLocationNo", VtuzxUtil.getString(doc, "toLocationNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("locationNo", VtuzxUtil.getString(doc, "locationNo"))
                .append("_createUserId", VtuzxUtil.getString(doc, "_createUserId"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_auditUserId", VtuzxUtil.getString(doc, "_auditUserId"))
                .append("auditUserName", VtuzxUtil.getString(doc, "auditUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "auditTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getAllocationHistoryDetail(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document allocationDoc = allocationDao.findOne(Criteria.where("billNo").is(billNo));
        VtuzxMap header = new VtuzxMap("billNo", billNo)
                .append("fromStockNo", VtuzxUtil.getString(allocationDoc, "fromStockNo"))
                .append("toStockNo", VtuzxUtil.getString(allocationDoc, "toStockNo"))
                .append("toLocationNo", VtuzxUtil.getString(allocationDoc, "toLocationNo"))
                .append("boxCount", VtuzxUtil.getInt(allocationDoc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(allocationDoc, "count"))
                .append("createUserName", VtuzxUtil.getBoolean(allocationDoc, "createUserName"))
                .append("allocationType", VtuzxUtil.getInt(allocationDoc, "allocationType"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(allocationDoc, "createTime")));

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("status", -1).append("TPALCount", 1).append("createTime", -1), 0, 0);

        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            VtuzxMap allocationDetails = new VtuzxMap(allocationDetailDoc);
            allocationDetails.remove(IVtuzxConst.Key_updateTime);
            allocationDetails.remove(IVtuzxConst.Key_createTime);
            String id = VtuzxUtil.removeString(allocationDetails, IVtuzxConst.Key__id);
            allocationDetails.append("id", id);
            dataList.add(allocationDetails);
        }

        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getAllocationHistoryDetailBox(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> boxItr = allocationDetailBoxDao.findList(Criteria.where("billNo").is(billNo), new Document("boxNo", 1), 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            VtuzxMap boxs = new VtuzxMap(boxDoc);
            boxs.remove(IVtuzxConst.Key_updateTime);
            boxs.remove(IVtuzxConst.Key_createTime);
            String boxId = VtuzxUtil.removeString(boxs, IVtuzxConst.Key__id);
            boxs.append("id", boxId);
            dataList.add(boxs);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBoxFromStock(ObjectId userId, String name, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String locationNo = VtuzxUtil.getString(param, "locationNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        Criteria cond = new Criteria();
        List<VtuzxMap> dataList = new ArrayList<>();

        if (!VtuzxUtil.isEmpty(boxNo)) {
            Document boxDoc = inventoryDetailDao.findOne(Criteria.where("boxNo").regex(boxNo).and("status").is("in"));
            if (!VtuzxUtil.isEmpty(boxDoc)) {
                String boxLocationNo = VtuzxUtil.getString(boxDoc, "locationNo");
                String rfid = VtuzxUtil.getString(boxDoc, "rfid");
                String trayNumber = VtuzxUtil.getString(boxDoc, "trayNumber");
                double count = VtuzxUtil.getDouble(boxDoc, "count");
                ObjectId inventoryId = VtuzxUtil.getObject(boxDoc, "_inventoryId");
                Document inventoryDoc = inventoryDao.findById(inventoryId);
                VtuzxMap data = new VtuzxMap(inventoryDoc);
                data.remove("boxCount");
                data.remove("count");
                data.append("id", VtuzxUtil.removeString(data, IVtuzxConst.Key__id));
                data.append("createUserId", VtuzxUtil.removeString(data, "_createUserId"));
                data.append("updateUserId", VtuzxUtil.removeString(data, "_updateUserId"));
                data.append("locationNo", boxLocationNo);
                data.append("rfid", rfid);
                data.append("count", count);
                data.append("boxNo", boxNo);
                data.append("trayNumber", trayNumber);
                String dataMaterialNo = VtuzxUtil.getString(data, "materialNo");
                Document material = materialDao.findOne(Criteria.where("fNumber").is(dataMaterialNo));
                data.append("materialName", VtuzxUtil.getString(material, "fName"));
                data.append("materialSpec", VtuzxUtil.getString(material, "fSpecification"));
                dataList.add(data);
            }
        } else if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) {
            if (!VtuzxUtil.isEmpty(materialNo)) {
                cond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                cond.and("batchNo").is(batchNo);
            }
            if (!VtuzxUtil.isEmpty(stockNo)) {
                cond.and("stockNo").is(stockNo);
            }
            List<ObjectId> ids = new ArrayList<>();
            Iterator<Document> inventoryItr = inventoryDao.findList(cond, null, 0, 0);
            while (inventoryItr.hasNext()) {
                Document inventoryDoc = inventoryItr.next();
                ObjectId id = VtuzxUtil.getObject(inventoryDoc, IVtuzxConst.Key__id);
                ids.add(id);
            }
            List<ObjectId> detailInventoryIdList = new ArrayList<>();
            Criteria inventoryDetailCond = new Criteria("_inventoryId").in(ids).and("status").is("in");

            if (!VtuzxUtil.isEmpty(locationNo)) {
                inventoryDetailCond.and("locationNo").is(locationNo);
            }
            Iterator<Document> inventoryDetailItr = inventoryDetailDao.findList(inventoryDetailCond, null, 0, 0);
            while (inventoryDetailItr.hasNext()) {
                Document detailDoc = inventoryDetailItr.next();
                VtuzxMap inventoryMap = new VtuzxMap(detailDoc);
                ObjectId inventoryId = VtuzxUtil.getObject(detailDoc, "_inventoryId");
                inventoryMap.append("id", VtuzxUtil.removeString(inventoryMap, IVtuzxConst.Key__id));
                inventoryMap.append("inventoryId", inventoryId);
                inventoryMap.append("createUserId", VtuzxUtil.removeString(inventoryMap, "_createUserId"));
                inventoryMap.append("updateUserId", VtuzxUtil.removeString(inventoryMap, "_updateUserId"));
                FastUtil.addToIdList(detailInventoryIdList, inventoryId);
                dataList.add(inventoryMap);
            }
            if (!VtuzxUtil.isEmpty(detailInventoryIdList)) {
                VtuzxMap detailInventoryMap = new VtuzxMap();
                Iterator<Document> detailInventoryItr = inventoryDao.findList(Criteria.where("_id").in(detailInventoryIdList), null, 0, 0);
                while (detailInventoryItr.hasNext()) {
                    Document inventoryDoc = detailInventoryItr.next();
                    String id = VtuzxUtil.getString(inventoryDoc, IVtuzxConst.Key__id);
                    detailInventoryMap.append(id, inventoryDoc);
                }
                for(VtuzxMap inventoryMap: dataList) {
                    String inventoryId = VtuzxUtil.getString(inventoryMap, "inventoryId");
                    Document inventoryDoc = VtuzxUtil.getObject(detailInventoryMap, inventoryId);
                    if (inventoryDoc != null) {
                        String inventoryMaterialNo = VtuzxUtil.getString(inventoryDoc, "materialNo");
                        String inventoryBatchNo = VtuzxUtil.getString(inventoryDoc, "batchNo");
                        String produceDate = VtuzxUtil.getString(inventoryDoc, "produceDate");
                        int exp = VtuzxUtil.getInt(inventoryDoc, "exp");
                        Document material = materialDao.findOne(Criteria.where("fNumber").is(inventoryMaterialNo));
                        inventoryMap.remove("createUserName");
                        inventoryMap.append("materialName", VtuzxUtil.getString(material, "fName"));
                        inventoryMap.append("materialSpec", VtuzxUtil.getString(material, "fSpecification"));
                        inventoryMap.append("unitName", VtuzxUtil.getString(material, "fBaseUnitIdFName"));
                        inventoryMap.append("unit", VtuzxUtil.getString(material, "fBaseUnitIdFNumber"));
                        inventoryMap.append("materialNo", inventoryMaterialNo);
                        inventoryMap.append("batchNo", inventoryBatchNo);
                        inventoryMap.append("createUserName", name);
                        inventoryMap.append("produceDate", produceDate);
                        inventoryMap.append("exp", exp);
                    }
                }
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getAllocationWebDetail(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        Criteria cond = new Criteria("billNo").is(billNo);
        if (!VtuzxUtil.isEmpty(allocationType)) {
            cond.and("allocationType").is(allocationType);
        }
        Document allocationDoc = allocationDao.findOne(cond);
        if (VtuzxUtil.isEmpty(allocationDoc)) {
            throw new VtuzxException("单号不存在！");
        }
        VtuzxMap header = new VtuzxMap(allocationDoc);
        header.append("id", VtuzxUtil.removeString(header, "_id"));
        header.append("createUserId", VtuzxUtil.removeString(header, "_createUserId"));
        header.append("updateUserId", VtuzxUtil.removeString(header, "_updateUserId"));
        header.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(header, "createTime")));
        header.append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(header, "updateTime")));
        header.append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(header, "auditTime")));

        List<VtuzxMap> allocationDetailList = new ArrayList<>();
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            VtuzxMap allocationDetailMap = new VtuzxMap(allocationDetailDoc);
            allocationDetailMap.append("id", VtuzxUtil.removeString(allocationDetailMap, "_id"));
            allocationDetailMap.append("createUserId", VtuzxUtil.removeString(allocationDetailMap, "_createUserId"));
            allocationDetailMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(allocationDetailMap, "createTime")));
            allocationDetailMap.append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(allocationDetailMap, "updateTime")));
            allocationDetailList.add(allocationDetailMap);
        }
        return new VtuzxMap("header", header).append("data", allocationDetailList);
    }

    @Override
    public VtuzxMap getAllocationWebDetailBox(ObjectId userId, String name, Map<String, Object> param) {
        List<VtuzxMap> dataList = new ArrayList<>();
        String id = VtuzxUtil.getString(param, "id");
        Iterator<Document> allocationDetailBoxItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(id), null, 0, 0);
        while (allocationDetailBoxItr.hasNext()) {
            Document allocationDetailBoxDoc = allocationDetailBoxItr.next();
            VtuzxMap allocationDetailBoxMap = new VtuzxMap(allocationDetailBoxDoc);
            allocationDetailBoxMap.append("id", VtuzxUtil.removeString(allocationDetailBoxMap, "_id"));
            allocationDetailBoxMap.append("detailId", VtuzxUtil.removeString(allocationDetailBoxMap, "_detailId"));
            allocationDetailBoxMap.append("createUserId", VtuzxUtil.removeString(allocationDetailBoxMap, "_createUserId"));
            allocationDetailBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(allocationDetailBoxMap, "createTime")));
            allocationDetailBoxMap.append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(allocationDetailBoxMap, "updateTime")));
            dataList.add(allocationDetailBoxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void updateAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        String stockNo = VtuzxUtil.getString(param, "toStockNo");
        String locationNo = VtuzxUtil.getString(param, "toLocationNo");
        Document doc = new Document("toStockNo", stockNo).append("toLocationNo", locationNo);
        allocationDetailDao.updateById(id, doc);
        allocationDetailBoxDao.updateMany(Criteria.where("_detailId").is(FastUtil.convertId(id)), doc);

    }

    @Override
    public void updateAllAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "toStockNo");
        String locationNo = VtuzxUtil.getString(param, "toLocationNo");
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        Document doc = new Document("toStockNo", stockNo).append("toLocationNo", locationNo);
        allocationDetailDao.updateMany(Criteria.where("isTemp").is(true).and("_createUserId").is(userId).and("allocationType").is(allocationType), doc);
        allocationDetailBoxDao.updateMany(Criteria.where("isTemp").is(true).and("_createUserId").is(userId).and("allocationType").is(allocationType), doc);

    }

    @Override
    public void issueUserAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String id = VtuzxUtil.getString(param, "id");
        allocationDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", "issue").append("_allocationUserId", FastUtil.convertId(id)));
        allocationDetailDao.updateMany(Criteria.where("billNo").is(billNo), new Document("status", "issue"));
        allocationDetailBoxDao.updateMany(Criteria.where("billNo").is(billNo), new Document("status", "issue"));
    }

    @Override
    public void unissueUserAllocation(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        allocationDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("status", "save")).append("$unset", new Document("_allocationUserId", 1)));
        allocationDetailDao.updateManyRedirect(Criteria.where("billNo").is(billNo), new Document("$unset", new Document("status", 1)));
        allocationDetailBoxDao.updateManyRedirect(Criteria.where("billNo").is(billNo), new Document("$unset", new Document("status", 1)));
    }

    @Override
    public VtuzxMap getAllocationTaskDetail(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document allocationDoc = allocationDao.findOne(Criteria.where("billNo").is(billNo));
        if (VtuzxUtil.isEmpty(allocationDoc)) {
            throw new VtuzxException("箱号不存在");
        }
        String toStockNo = VtuzxUtil.getString(allocationDoc, "toStockNo");
        String toLocationNo = VtuzxUtil.getString(allocationDoc, "toLocationNo");

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo).and("status").is("issue"), null, 0, 0);
        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            VtuzxMap allocationDetailMap = new VtuzxMap(allocationDetailDoc);
            allocationDetailMap.append("id", VtuzxUtil.removeString(allocationDetailMap, "_id"));
            allocationDetailMap.append("createUserId", VtuzxUtil.removeString(allocationDetailMap, "_createUserId"));
            allocationDetailMap.remove("updateTime");
            allocationDetailMap.remove("createTime");
            dataList.add(allocationDetailMap);
        }

        for (VtuzxMap data: dataList) {
            String id = VtuzxUtil.getString(data, "id");
            int sumBoxCount = 0;
            double sumCount = 0d;
            Iterator<Document> boxItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(FastUtil.convertId(id)).and("status").is("issue"), null, 0, 0);
            while (boxItr.hasNext()) {
             Document boxDoc = boxItr.next();
             double count = VtuzxUtil.getDouble(boxDoc, "count");
             sumBoxCount ++;
             sumCount += count;
            }
            data.append("nowBoxCount", sumBoxCount).append("nowCount", sumCount);
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("toStockNo", toStockNo).append("toLocationNo", toLocationNo);
    }

    @Override
    public VtuzxMap getAllocationTaskDetailBox(ObjectId userId, String name, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> allocationDetailItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(FastUtil.convertId(id)).and("status").is("issue"), null, 0, 0);
        while (allocationDetailItr.hasNext()) {
            Document allocationDetailDoc = allocationDetailItr.next();
            VtuzxMap allocationDetailMap = new VtuzxMap(allocationDetailDoc);
            allocationDetailMap.append("id", VtuzxUtil.removeString(allocationDetailMap, "_id"));
            allocationDetailMap.append("createUserId", VtuzxUtil.removeString(allocationDetailMap, "_createUserId"));
            allocationDetailMap.remove("updateTime");
            allocationDetailMap.remove("createTime");
            dataList.add(allocationDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void addTaskAllocationBox(ObjectId userId, String name, Map<String, Object> param) {
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        allocationDetailBoxDao.updateOneRedirect(Criteria.where("boxNo").is(boxNo), new Document("$unset", new Document("status", 1)));
        Document doc = allocationDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
        ObjectId detailId = VtuzxUtil.getObject(doc, "_detailId");
        Iterator<Document> detailItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(detailId).and("status").is("issue"), null, 0, 0);
        VtuzxMap detailMap = FastUtil.itr2Map(detailItr, "_id");
        if (detailMap.size() == 0) {
            allocationDetailDao.updateByIdRedirect(detailId, new Document("$unset", new Document("status", 1)));
        }
    }

    @Override
    public void rfidAddTaskAllocationBox(ObjectId userId, String name, Map<String, Object> param) {
        List<String> rfidList = VtuzxUtil.getObject(param, "rfidList");
        allocationDetailBoxDao.updateOneRedirect(Criteria.where("rfid").in(rfidList), new Document("$unset", new Document("status", 1)));
        String rfid = rfidList.get(0);
        Document boxDoc = allocationDetailBoxDao.findOne(Criteria.where("rfid").is(rfid));
        String billNo = VtuzxUtil.getString(boxDoc, "billNo");
        List<String> detailList = new ArrayList<>();
        Iterator<Document> detailItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        VtuzxMap detailMap = FastUtil.itr2Map(detailItr, "_id");
        detailMap.forEach((k, v) -> {
            detailList.add(k);
        });

        for (String id: detailList) {
            Iterator<Document> boxItr = allocationDetailBoxDao.findList(Criteria.where("_detailId").is(FastUtil.convertId(id)).and("status").is("issue"), null, 0, 0);
            VtuzxMap box = FastUtil.itr2Map(boxItr, "_id");
            if (box.size() == 0) {
                allocationDetailDao.updateByIdRedirect(FastUtil.convertId(id), new Document("$unset", new Document("status", 1)));
            }
        }
    }

    @Override
    public VtuzxMap getTaskAllocationBox(ObjectId userId, String name, Map<String, Object> param) {
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        Document allocationDetailBoxDoc = allocationDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
        return new VtuzxMap(allocationDetailBoxDoc);

    }

    @Override
    public VtuzxMap getTaskAllocationBoxRfid(ObjectId userId, String name, Map<String, Object> param) {
        List<VtuzxMap> rfid = new ArrayList<>();
        List<String> rfidList = VtuzxUtil.getObject(param, "rfidList");
        Iterator<Document> allocationDetailBoxItr = allocationDetailBoxDao.findList(Criteria.where("rfid").in(rfidList), null, 0, 0);
        while (allocationDetailBoxItr.hasNext()) {
            Document document = allocationDetailBoxItr.next();
            VtuzxMap map = new VtuzxMap(document);
            rfid.add(map);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, rfid);
    }

    @Override
    public VtuzxMap getSaleAllocationAddMaterialCount(ObjectId userId, String name, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String billNo = VtuzxUtil.getString(param, "billNo");

        List<Document> saleStoreList = new ArrayList<>();
        Iterator<Document> saleStoreBoxItr = saleStoreDetailDao.findList(Criteria.where("billNo").is(billNo), null,0,0);
        while (saleStoreBoxItr.hasNext()) {
            Document saleStoreBox = saleStoreBoxItr.next();
            saleStoreList.add(saleStoreBox);
        }

        List<Document> allDocList = new ArrayList<>();
        Iterator<Document> allocationBoxItr = allocationDetailBoxDao.findList(Criteria.where("stockNo").is(stockNo).and("isTemp").is(true).and("isSale").is(true).and("_createUserId").is(userId), null,0,0);
        while (allocationBoxItr.hasNext()) {
            Document allocationBox = allocationBoxItr.next();
            allDocList.add(allocationBox);
        }
//
//        VtuzxMap materialCountMap = new VtuzxMap();
//        for (Document allDoc: allDocList) {
//            String materialNo = VtuzxUtil.getString(allDoc, "materialNo");
//            int count = VtuzxUtil.getInt(materialCountMap, materialNo);
//            count++;
//            materialCountMap.append(materialNo, count);
//        }
//
        VtuzxMap dataMap = new VtuzxMap();
//        for (Document saleStore: saleStoreList) {
//            String materialNo = VtuzxUtil.getString(saleStore, "materialNo");
//            int count = VtuzxUtil.getInt(materialCountMap, materialNo);
//            dataMap.append(materialNo, count);
//        }

        for (Document saleStore: saleStoreList) {
            String materialNo = VtuzxUtil.getString(saleStore, "materialNo");
            for (Document allDoc: allDocList) {
                String allMaterialNo = VtuzxUtil.getString(allDoc, "materialNo");
                if (materialNo.equals(allMaterialNo)) {
                    int count = VtuzxUtil.getInt(dataMap, materialNo);
                    count++;
                    dataMap.append(materialNo, count);
                }
            }
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataMap);
    }

    @Override
    public VtuzxMap getSaleAllocationAddMaterialBox(ObjectId userId, String name, Map<String, Object> param) {
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        List<Document> boxList = new ArrayList<>();
        Iterator<Document> boxItr = allocationDetailBoxDao.findList(Criteria.where("materialNo").is(materialNo).and("isTemp").is(true).and("isSale").is(true), null, 0, 0);
        while (boxItr.hasNext()) {
            boxList.add(boxItr.next());
        }
        return new VtuzxMap(IVtuzxConst.Key_data, boxList);
    }

    @Override
    public void deleteSaleAllocationAddMaterialBox(ObjectId userId, String name, Map<String, Object> param) {
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        allocationDetailBoxDao.deleteOne(Criteria.where("boxNo").is(boxNo).and("isSale").is(true).and("isTemp").is(true));
    }

    /**
     * 下载pda调拨单
     * @param token
     * @param param
     * @return
     */
    @Override
    public VtuzxDownloadBean downloadPdaAllocation(VtuzxToken token, Map<String, Object> param) throws Exception {
        String allocationType = VtuzxUtil.getString(param, "allocationType");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String toStockNo = VtuzxUtil.getString(param, "toStockNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        String auditUserName = VtuzxUtil.getString(param, "auditUserName");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        List<String> auditTime = VtuzxUtil.getObject(param, "auditTime");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        cond.and("count").gt(0);
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(allocationType)) {
            cond.and("allocationType").is(allocationType);
        }
        if (!VtuzxUtil.isEmpty(toStockNo)) {
            cond.and("toStockNo").is(toStockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            cond.and("createUserName").regex(createUserName);
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(auditUserName)) {
            cond.and("auditUserName").regex(auditUserName);
        }
        if (!VtuzxUtil.isEmpty(auditTime)) {
            cond.and("auditTime").gte(VtuzxUtil.parseDate(auditTime.get(0))).lte(VtuzxUtil.parseDate(auditTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            List<Document> allocationDetailList = new ArrayList<>();
            Iterator<Document> allocationDetailItr = allocationDetailDao.findList(pickCond, new Document("createTime",-1), 0, 0);
            while (allocationDetailItr.hasNext()) {
                Document allocationDetailDoc = allocationDetailItr.next();
                allocationDetailList.add(allocationDetailDoc);
            }

        }

        List<String> billNoList = new ArrayList<>();
        Iterator<Document> allicationItr = allocationDao.findList(cond,new Document("createTime",-1),0,0);
        while (allicationItr.hasNext()){
            Document allocationDoc = allicationItr.next();
            String allocationNo = VtuzxUtil.getString(allocationDoc,"billNo");
            if (!billNoList.contains(allocationNo)){
                billNoList.add(allocationNo);
            }
        }
        List<Document> detailList = new ArrayList<>();
        List<String> stockNoList = new ArrayList<>();//仓库编号集合
        Iterator<Document> allocationDetailItr = allocationDetailDao.findList(Criteria.where("billNo").in(billNoList),
                new Document("createTime",-1),0,0);
        while (allocationDetailItr.hasNext()){
            Document detailDoc = allocationDetailItr.next();
            String cuStockNo = VtuzxUtil.getString(detailDoc,"stockNo");//原仓库编号
            String alStockNo = VtuzxUtil.getString(detailDoc,"toStockNo");//调拨仓库编号
            if(!stockNoList.contains(cuStockNo)){
                stockNoList.add(cuStockNo);
            }
            if (!stockNoList.contains(alStockNo)){
                stockNoList.add(alStockNo);
            }
            detailList.add(detailDoc);
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        //循环添加仓库信息
        for (Document detail : detailList){
            String cuStockNo = VtuzxUtil.getString(detail,"stockNo");//原仓库编号
            String alStockNo = VtuzxUtil.getString(detail,"toStockNo");//调拨仓库编号
            String cuStockName = VtuzxUtil.getString(stockMap,cuStockNo);//调拨仓库名称
            String alStockName = VtuzxUtil.getString(stockMap,alStockNo);//调拨仓库名称
            detail.append("stockName",cuStockName)
                    .append("toStockName",alStockName);
        }
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "其他入库详情");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "单据编号"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col++, "仓库"),
                new VtuzxExcelCell(col++, "仓位"),
                new VtuzxExcelCell(col++, "调拨至仓库"),
                new VtuzxExcelCell(col++, "调拨至仓位"),
                new VtuzxExcelCell(col++, "物料编码"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "物料规格"),
                new VtuzxExcelCell(col++, "单位"),
                new VtuzxExcelCell(col++, "批次"),
                new VtuzxExcelCell(col++, "箱数"),
                new VtuzxExcelCell(col++, "重量")
        ));
        sheet0.addRow(header0);
        for (Document detail : detailList) {
            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.formatYmdHmF(VtuzxUtil.getObject(detail, "createTime"))),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "stockName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "locationNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "toStockName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "toLocationNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "unit")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "batchNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "boxCount")),
                    new VtuzxExcelCell(col, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())

            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 300},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 150},
                new int[]{7, 150},
                new int[]{8, 150},
                new int[]{8, 150}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("调拨详情" + timestamp + ".xlsx", stream);
    }

}